﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Media;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Forms.Integration;

using Microsoft.Office.Core;
using Microsoft.Office.Interop.Word;

using Writespace.Dialogs;
using MessageBox = System.Windows.Forms.MessageBox;
using Word = Microsoft.Office.Interop.Word;
using Office = Microsoft.Office.Core;

namespace Writespace2003
{
    public partial class ThisAddIn
    {
        private Word.Application myApplication;
        private CommandBarButton myControl;
        private CommandBarButton menuCommand;

        private void ThisAddIn_Startup(object sender, EventArgs e)
        {
            myApplication = Application;
            RemoveMenuItems();
            AddMenuItems();
        }

        private static void ThisAddIn_Shutdown(object sender, EventArgs e)
        {
        }

        #region Menu items 

        private void RemoveMenuItems()
        {
            foreach (CommandBarControl control in myApplication.CommandBars["Text"].Controls)
            {
                if (control != null)
                    Debug.Print("Found " + control.Caption);
            }

            RemoveExistingMainMenuItems("Writespace");
            RemoveExistingPopupMenuItems("Writespace");
        }

        private void AddMenuItems()
        {
            AddPopopMenuItem();
            AddMainMenuItem();
        }

        private void AddMainMenuItem()
        {
            try
            {
                var menubar = Application.CommandBars.ActiveMenuBar;

                var cmdBarControl = (CommandBarPopup)menubar.Controls.Add(MsoControlType.msoControlPopup, missing, missing, menubar.Controls.Count, true);

                if (cmdBarControl != null)
                {
                    cmdBarControl.Tag = "WritespaceMainMenuItem";
                    cmdBarControl.Caption = "&Writespace";

                    menuCommand = (CommandBarButton)cmdBarControl.Controls.Add(MsoControlType.msoControlButton, missing, missing, missing, true);
                    menuCommand.Caption = "&Enter Writespace";
                    menuCommand.Tag = "WritespaceSubMenuItem";
                    menuCommand.Click += EnterWritespace_Click;

                    menuCommand = (CommandBarButton)cmdBarControl.Controls.Add(MsoControlType.msoControlButton, missing, missing, missing, true);
                    menuCommand.Caption = "&Writespace Options...";
                    menuCommand.Tag = "WritespaceOptionsSubMenuItem";
                    menuCommand.Click += WritespaceOptions_Click;
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        private static void WritespaceOptions_Click(CommandBarButton Ctrl, ref bool CancelDefault)
        {
            OptionsButton_Click();
        }

        private static void EnterWritespace_Click(CommandBarButton Ctrl, ref bool CancelDefault)
        {
            WritespaceButton_Click();
        }


        private void AddPopopMenuItem()
        {
            var menuItem = MsoControlType.msoControlButton;

            myControl = (CommandBarButton)myApplication.CommandBars["Text"].Controls.Add(menuItem, missing, missing, 1, true);
            myControl.Style = MsoButtonStyle.msoButtonCaption;
            myControl.Caption = "Writespace";
            myControl.Tag = "Writespace";

            myControl.Click += myControl_Click;
        }

        private void RemoveExistingMainMenuItems(string tag)
        {
            try
            {

                var menubar = Application.CommandBars.ActiveMenuBar;
                foreach (var control in menubar.Controls)
                {
                    if (control is CommandBarPopup)
                    {

                        var caption = ((CommandBarPopup)control).Caption;
                        Debug.Print("Menu:" + caption);
                        if (caption.Contains(tag))
                            ((CommandBarPopup)control).Delete(true);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }


        private void RemoveExistingPopupMenuItems(string tag)
        {
            try
            {

                foreach (var control in myApplication.CommandBars["Text"].Controls)
                {
                    if (control is CommandBarButton)
                    {

                        var caption = ((CommandBarButton)control).Caption;
                        Debug.Print("Popup:" + caption);
                        if (caption.Contains(tag))
                            ((CommandBarButton)control).Delete(true);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        #endregion
        
        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            Startup += ThisAddIn_Startup;
            Shutdown += ThisAddIn_Shutdown;
        }

        #endregion

        private static void myControl_Click(CommandBarButton Ctrl, ref bool CancelDefault)
        {
            WritespaceButton_Click();
        }

        private static void CreateEditor(Screen screen)
        {
            var editor = new TextEditorWindow
            {
                WindowStartupLocation = WindowStartupLocation.Manual,
                Left = screen.WorkingArea.Left,
                Top = screen.WorkingArea.Top,
                Width = screen.WorkingArea.Width,
                Height = screen.WorkingArea.Height,
                Text = Globals.ThisAddIn.Application.ActiveDocument.Content.Text,
                ParentId = Globals.ThisAddIn.Application.ActiveDocument.Name
            };


            editor.Closing += Editor_Closing;
            editor.Save += Editor_Save;
            editor.ToggleMonitor += Editor_ToggleMonitor;

            ElementHost.EnableModelessKeyboardInterop(editor);

            editor.Show();

            editor.WindowState = WindowState.Maximized; //do this after Show() or won't draw on secondary screens
            editor.Focus();
        }

        private static void WritespaceButton_Click()
        {
            if (!IsValidWordDocument()) return;

            if (Properties.Settings.Default.Screen > SystemInformation.MonitorCount)
            {
                Properties.Settings.Default.Screen = 1;
                Properties.Settings.Default.Save();
            }

            var screen = Screen.AllScreens[Properties.Settings.Default.Screen - 1];
            CreateEditor(screen);
        }

        private static void OptionsButton_Click()
        {
            var optionsDialog = new OptionsWindow();
            ElementHost.EnableModelessKeyboardInterop(optionsDialog);
            optionsDialog.Show();

        }

        private static bool IsValidWordDocument()
        {
            if (Globals.ThisAddIn.Application.ActiveDocument.InlineShapes.Count > 0)
            {
                MessageBox.Show(
                    "This document contains inline shapes and should not be edited with Writespace. Make sure you are working on a text only document and try again.",
                    "Document Content Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            if (Globals.ThisAddIn.Application.ActiveDocument.Shapes.Count > 0)
            {
                MessageBox.Show(
                    "This document contains shapes and should not be edited with Writespace. Make sure you are working on a text only document and try again.",
                    "Document Content Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            if (Globals.ThisAddIn.Application.ActiveDocument.FormFields.Count > 0)
            {
                MessageBox.Show(
                    "This document contains form fields and should not be edited with Writespace. Make sure you are working on a text only document and try again.",
                    "Document Content Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            if (Globals.ThisAddIn.Application.ActiveDocument.Frames.Count > 0)
            {
                MessageBox.Show(
                    "This document contains frames and should not be edited with Writespace. Make sure you are working on a text only document and try again.",
                    "Document Content Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            if (Globals.ThisAddIn.Application.ActiveDocument.Tables.Count > 0)
            {
                MessageBox.Show(
                    "This document contains tables and should not be edited with Writespace. Make sure you are working on a text only document and try again.",
                    "Document Content Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            return true;
        }

        #region Editor Window Events


        const int PRIMARY_SCREEN = 0;
        const int SECONDARY_SCREEN = 1;

        //TODO: Move this code to the editor instead, no need to have it here
        private static void Editor_ToggleMonitor(object sender, EventArgs e)
        {
            var editor = sender as TextEditorWindow;
            Debug.Assert(editor != null, "Editor was null, should never happen.");

            if (SystemInformation.MonitorCount < 2)
            {
                SystemSounds.Beep.Play();
                editor.Status = "Only 1 monitor available!";
                return;
            }

            Screen screen;
            switch (Properties.Settings.Default.Screen)
            {
                case 1:
                    screen = Screen.AllScreens[SECONDARY_SCREEN];
                    Properties.Settings.Default.Screen = 2;
                    break;
                case 2:
                    screen = Screen.AllScreens[PRIMARY_SCREEN];
                    Properties.Settings.Default.Screen = 1;
                    break;
                default:
                    screen = Screen.AllScreens[PRIMARY_SCREEN];
                    Properties.Settings.Default.Screen = 1;
                    break;
            }
            Properties.Settings.Default.Save();

            UpdateDocumentTextFromEditor(sender, true);
            editor.Close();
            CreateEditor(screen);
        }

        private static void Editor_Save(object sender, EventArgs e)
        {
            //Grab text
            var document = UpdateDocumentTextFromEditor(sender, false);

            Debug.Assert(document != null, "Document was null, should never happen.");

            try
            {
                document.Save();
            }
            catch (Exception ex)
            {
                //this may happen if user escaped from the save dialog
                Debug.Print("Exception while saving document: " + ex);
                return;
            }

            var editor = sender as TextEditorWindow;

            Debug.Assert(editor != null, "Editor was null, should never happen.");

            editor.ParentId = document.Name;
            editor.Status = "Saved " + document.Name;
        }

        private static void Editor_Closing(object sender, CancelEventArgs e)
        {
            UpdateDocumentTextFromEditor(sender, true);
        }

        private static Document UpdateDocumentTextFromEditor(object sender, bool activateDocument)
        {
            var editor = sender as TextEditorWindow;

            if (editor == null) Debug.Print("Document was null, should never happen.");

            if (editor != null)
            {
                //find correct word document, in case the user has opened several word docs
                foreach (Document document in Globals.ThisAddIn.Application.Documents)
                {
                    if (document.Name == editor.ParentId)
                    {
                        document.Content.Text = editor.Text;
                        if (activateDocument)
                            document.Activate();
                        return document;
                    }
                }

                MessageBox.Show("Could not find parent document '" + editor.ParentId +
                                "', did you close it? Creating a new document and dumping the text into that instead.");

                object missing = System.Reflection.Missing.Value;
                object isVisible = true;
                var newDoc = Globals.ThisAddIn.Application.Documents.Add(ref missing, ref missing, ref missing, ref isVisible);
                if (activateDocument)
                    newDoc.Activate();
                newDoc.Content.Text = editor.Text;
                return newDoc;
            }

            MessageBox.Show("Could not get hold of the Writespace editor window, which is very weird. I cannot handle this.");
            return null;
        }

        #endregion

    }
}
